package main

import (
	"blogcenter/internal/biz"
	"blogcenter/internal/config"
	mqs "blogcenter/internal/consumer"
	"blogcenter/internal/handler"
	"blogcenter/internal/logic/authblog"
	"blogcenter/internal/logic/authlike"
	"blogcenter/internal/svc"
	"context"
	"flag"
	"fmt"
	"net/http"
	"time"

	"github.com/hashicorp/consul/api"
	"github.com/zeromicro/go-zero/core/conf"
	"github.com/zeromicro/go-zero/core/service"
	"github.com/zeromicro/go-zero/rest"
	"github.com/zeromicro/go-zero/rest/httpx"
	"github.com/zeromicro/zero-contrib/zrpc/registry/consul"
)

var configFile = flag.String("f", "etc/blogcenter-api.yaml", "the config file")

func main() {
	flag.Parse()

	// 设置全局错误处理器
	httpx.SetErrorHandler(func(err error) (int, interface{}) {
		// 判断是否为自定义错误
		if bizErr, ok := err.(*biz.BizError); ok {
			return http.StatusOK, map[string]interface{}{
				"code":    bizErr.Code, // 动态错误码
				"message": bizErr.Message,
			}
		}

		// 默认错误（未识别的错误类型）
		return http.StatusOK, map[string]interface{}{
			"code":    -1, // 默认错误码
			"message": err.Error(),
		}
	})

	// 1. 加载本地基础配置
	var baseConfig config.BaseConfig
	conf.MustLoad(*configFile, &baseConfig)
	config.SetBaseConfig(baseConfig) // 设置到全局变量中

	// 2. 从Consul KV加载配置
	kvConfig, err := loadConfigFromConsulKV(
		baseConfig.Consul.Host,
		baseConfig.Consul.ConfigKey,
		baseConfig.Consul.Token,
	)
	if err != nil {
		panic(fmt.Errorf("failed to load config from consul kv: %v", err))
	}

	// 3. 解析合并配置
	var c config.Config
	if err := conf.LoadFromJsonBytes(kvConfig, &c); err != nil {
		panic(fmt.Errorf("failed to parse consul kv config: %v", err))
	}

	// 4. 注册服务到Consul
	listenOn := fmt.Sprintf("%s:%d", c.Host, c.Port)
	err = consul.RegisterService(listenOn, consul.Conf{
		Host:  baseConfig.Consul.Host,
		Key:   baseConfig.Consul.Key,
		Token: baseConfig.Consul.Token,
		TTL:   baseConfig.Consul.TTL,
	})
	if err != nil {
		panic(err)
	}

	// 5. 创建服务上下文
	ctx := svc.NewServiceContext(c)

	// 6. 创建服务组
	serviceGroup := service.NewServiceGroup()
	defer serviceGroup.Stop()

	// 7. 添加HTTP服务（总是启动，不检查模式）
	server := rest.MustNewServer(c.RestConf)
	defer server.Stop()
	handler.RegisterHandlers(server, ctx)
	serviceGroup.Add(server)

	// // 8. 添加Kafka消费者服务
	// kafkaConsumers := mqs.Consumers(c, context.Background(), ctx)
	// for _, consumer := range kafkaConsumers {
	//     serviceGroup.Add(consumer)
	// }

	// 9. 打印服务初始化状态
	printServiceStatus(ctx, listenOn)

	// 添加Kafka消费者服务（修正参数传递）
	backgroundCtx := context.Background() // 创建新的context
	kafkaConsumers := mqs.StartConsumers(c, backgroundCtx, ctx)
	for _, consumer := range kafkaConsumers {
		serviceGroup.Add(consumer)
	}

	// 启动阅读量同步服务
	go authblog.StartReadCountSyncService(ctx)
	go authlike.StartLikeSyncService(ctx)
	go authlike.StartCommentLikeSyncService(ctx)
	// 10. 启动服务
	fmt.Printf("Starting server at %s...\n", listenOn)
	serviceGroup.Start()
}

func loadConfigFromConsulKV(consulHost, consulKey, consulToken string) ([]byte, error) {
	config := api.DefaultConfig()
	config.Address = consulHost
	config.Token = consulToken
	config.WaitTime = 5 * time.Second

	client, err := api.NewClient(config)
	if err != nil {
		return nil, fmt.Errorf("failed to create consul client: %v", err)
	}

	kv := client.KV()
	pair, _, err := kv.Get(consulKey, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get kv from consul: %v", err)
	}

	if pair == nil {
		return nil, fmt.Errorf("no such key in consul: %s", consulKey)
	}

	return pair.Value, nil
}

func printServiceStatus(ctx *svc.ServiceContext, listenOn string) {
	fmt.Println("\n=== 服务初始化状态 ===")
	fmt.Printf("服务地址: %s\n", listenOn)
	fmt.Printf("数据库: %v\n", ctx.DB != nil)
	fmt.Printf("Redis: %v\n", ctx.Redis != nil)
	fmt.Printf("MinIO: %v\n", ctx.MinioClient != nil)
	fmt.Printf("Kafka生产者: %v\n", ctx.KafkaPusher != nil)
	fmt.Printf("JWT配置: %+v\n", ctx.Config.JWT)
	fmt.Printf("Redis配置: %+v\n", ctx.Config.Redis)
	fmt.Printf("MinIO配置: %+v\n", ctx.Config.Minio)
	fmt.Printf("Kafka配置: %+v\n", ctx.Config.Kafka)
	fmt.Printf("Gorse配置: %+v\n", ctx.Config.Gorse)
	fmt.Println("====================")
}
